package com.elite.groovy.callback

import com.alibaba.fastjson.JSONObject
import com.elite.groovy.kh.KHDBConfig
import com.elite.groovy.kh.KHUtil
import com.elite.groovy.util.EliteBean
import com.elite.groovy.util.Util
import org.apache.commons.logging.Log
import org.apache.commons.logging.LogFactory
import org.springframework.jdbc.core.JdbcTemplate

import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse

/**
 * @projectName: ngsapi_cs
 * @package: cn.com.callback
 * @className: apiWXLogin
 * @author: LiJT
 * @description: 嵌入腾讯的中间页面调用此接口实现信息验证重定向-腾讯体系下Step2
 * @date: 2022-12-19 14:03
 * @version: 1.0
 */

public class apiNGSLogin implements ServiceBackInvoke {
    private static final Log log = LogFactory.getLog(apiNGSLogin.class);
    private static String out_DomainURL = "";

    public String doCallBack(EliteBean eliteBean, HttpServletRequest request, HttpServletResponse response) {

        response.setCharacterEncoding("UTF-8");
        response.setContentType("application/json;charset=UTF-8");

        try {


            // 获取系统对外域名
            out_DomainURL = KHUtil.isNull(out_DomainURL) ? KHDBConfig.getAPIURL(eliteBean, "SYS-OuterDomain") : out_DomainURL;
            out_DomainURL = out_DomainURL.endsWith("/") ? out_DomainURL : out_DomainURL + "/";

            // 调用类型校验,此接口仅支持GET
            String getMethod = request.getMethod();
            log.debug("getMethod:" + getMethod);
            if (!getMethod.equals("GET")) {
                log.error("HTTP请求调用类型错误，接口调用失败：" + getMethod);
                response.sendRedirect(out_DomainURL + "ngs/404.html?ErrorTitle=" + URLEncoder.encode("页面异常", "UTF-8") + "&ErrorInfo=" + URLEncoder.encode("HTTP请求调用类型错误，接口调用失败：" + getMethod, "UTF-8").replaceAll("\\+", "%20"));
            }

            // 获取所有Header
            Map<String, String> mapHeader = new HashMap<String, String>();
            Enumeration headerNames = request.getHeaderNames();
            while (headerNames.hasMoreElements()) {
                String key = (String) headerNames.nextElement();
                String value = request.getHeader(key);
                log.debug("Call Header-" + key + ":" + value);

                mapHeader.put(key, value);
            }

            // 获取所有参数名
            Map<String, String> mapParams = new HashMap<String, String>();
            Enumeration ep = request.getParameterNames();
            while (ep.hasMoreElements()) {
                String key = (String) ep.nextElement();
                String value = request.getParameter(key);
                log.debug("Call Parameter-" + key + ":" + value);
                mapParams.put(key, value);

            }

            // 获取调用数据
            String Syncpram = request.getQueryString();
            log.info("接收调用GET参数信息：" + Syncpram);

            // 获取登录类型 是否Step2回调 1是 其他否
            String callback_Flag = request.getParameter("callback"); // 是否2次回调

            if (callback_Flag == "1") {
                return doLoginNGSDyn(eliteBean, response, mapParams);

            } else {
                String redirect_Flag = request.getParameter("redirect"); // 是否中间页redirect
                if (redirect_Flag == "1") {
                    return doLoginhtml(eliteBean, response, mapParams);
                } else {
                    return doLoginRedirect(eliteBean, response, mapParams);
                }

            }
        } catch (Exception e) {
            log.error(Util.getERRO(e));
            errorRedirect(response, "页面异常", "页面处理异常:" + e.getMessage());
        }

    }

    // Step1 初次嵌入请求 直接重定向腾讯
    public static String doLoginRedirect(EliteBean eliteBean, HttpServletResponse response, Map<String, String> mapParams) {

        // 获取数据源List<Map<String, Object>>
        JdbcTemplate jt = new JdbcTemplate(eliteBean.getDataSource());

        log.debug("初次嵌入请求 返回Html页面参数信息【mapParams】：" + mapParams);
        String opsource = mapParams.get("opsource"); // Html添加

        if (KHUtil.isNull(opsource)) {
            log.warn("打开页面异常opsource为空:" + opsource);
            response.sendRedirect(out_DomainURL + "ngs/404.html?ErrorTitle=" + URLEncoder.encode("页面异常", "UTF-8") + "&ErrorInfo=" + URLEncoder.encode("错误代码：DynNull 描述:页面ID错误", "UTF-8").replaceAll("\\+", "%20"));

        } else {

            String oauth2_URL = KHDBConfig.getParamConfig(eliteBean, opsource + "-oauth2");

            // 调用腾讯获取OPENID
            String appID = KHDBConfig.getParamConfig(eliteBean, opsource + "-appID");
            String agentID = KHDBConfig.getParamConfig(eliteBean, "QW_AgentID");
            log.debug("获取到的腾讯公众号配置信息【appID】：" + appID + "【agentID】：" + agentID);

            // 增加参数标识是二步回调
            mapParams.put("callback", "1");
            String queryStr = getQueryString(mapParams);
            String redirect_uri = out_DomainURL + "groovy/GeneralService/apiNGSLogin?" + queryStr;
            log.debug("获取到的腾讯公众号配置信息【queryStr】：" + queryStr + "【redirect_uri】：" + redirect_uri);

            // 基础参数为空直接重定向返回失败
            if (KHUtil.isNull(appID) || KHUtil.isNull(agentID) || KHUtil.isNull(queryStr)) {
                errorRedirect(response, "页面异常", "基础参数为空(appID,agentID,queryStr)");
            }

            oauth2_URL = oauth2_URL.replace('''${redirect_uri}''', encode(redirect_uri)).replace('''${appid}''', appID).replace('''${agentid}''', agentID);
            log.debug("获取到返回oauth2_URL【oauth2_URL】：" + oauth2_URL);

            // 基础参数为空直接重定向返回失败
            if (KHUtil.isNull(oauth2_URL)) {
                errorRedirect(response, "页面异常", "页面oauth2_URL加载错误");
            } else {
                response.sendRedirect(oauth2_URL);
            }
        }
    }


    // Step1 初次嵌入请求 返回Html页面
    public static String doLoginhtml(EliteBean eliteBean, HttpServletResponse response, Map<String, String> mapParams) {

        // 获取数据源List<Map<String, Object>>
        JdbcTemplate jt = new JdbcTemplate(eliteBean.getDataSource());

        log.debug("初次嵌入请求 返回Html页面参数信息【mapParams】：" + mapParams);
        String opsource = mapParams.get("opsource"); // Html添加

        if (KHUtil.isNull(opsource)) {
            log.warn("打开页面异常opsource为空:" + opsource);
            response.sendRedirect(out_DomainURL + "ngs/404.html?ErrorTitle=" + URLEncoder.encode("页面异常", "UTF-8") + "&ErrorInfo=" + URLEncoder.encode("错误代码：DynNull 描述:页面ID错误", "UTF-8").replaceAll("\\+", "%20"));

        } else {

            String initHtml = KHDBConfig.getParamConfig(eliteBean, opsource + "-initHtml");

            // 调用腾讯获取OPENID
            String appID = KHDBConfig.getParamConfig(eliteBean, opsource + "-appID");
            String agentID = KHDBConfig.getParamConfig(eliteBean, "QW_AgentID");

            // 增加参数标识是二步回调
            mapParams.put("callback", "1");
            String queryStr = getQueryString(mapParams);
            log.debug("获取到的腾讯公众号配置信息【appID】：" + appID + "【agentID】：" + agentID + "【queryStr】：" + queryStr);

            // 基础参数为空直接重定向返回失败
            if (KHUtil.isNull(appID) || KHUtil.isNull(agentID) || KHUtil.isNull(queryStr)) {
                errorRedirect(response, "页面异常", "基础参数为空(appID,agentID,queryStr)");
            }

            initHtml = initHtml.replace('''${out_DomainURL}''', out_DomainURL).replace('''${QueryParams}''', getQueryString(mapParams)).replace('''${appid}''', appID).replace('''${agentid}''', agentID);
            log.debug("获取到返回Html页面【initHtml】：" + initHtml);

            // 基础参数为空直接重定向返回失败
            if (KHUtil.isNull(initHtml)) {
                errorRedirect(response, "页面异常", "页面加载错误");
            } else {
                response.setContentType("text/html");
                return initHtml;
            }
        }
    }

    // Step2 二次回调请求 返回NGS重定向页面
    public static void doLoginNGSDyn(EliteBean eliteBean, HttpServletResponse response, Map<String, String> mapParams) {

        // 获取数据源List<Map<String, Object>>
        JdbcTemplate jt = new JdbcTemplate(eliteBean.getDataSource());

        String opsource = mapParams.containsKey("opsource") ? mapParams.get("opsource") : ""; // Html添加
        String opdynid = mapParams.containsKey("opdynid") ? mapParams.get("opdynid") : ""; // *手动-页面ID
        String taskid = mapParams.containsKey("taskid") ? mapParams.get("taskid") : ""; // *手动-业务数据ID
        String expand = mapParams.containsKey("expand") ? mapParams.get("expand") : ""; // *手动-拓展信息
        String code = mapParams.containsKey("code") ? mapParams.get("code") : ""; // 腾讯自动添加
        String state = mapParams.containsKey("state") ? mapParams.get("state") : ""; // Html添加
        log.debug("回调参数信息【code】：" + code + "【state】：" + state + "【opsource】：" + opsource + "【opdynid】：" + opdynid + "【taskid】：" + taskid + "【expand】：" + expand);

        if (KHUtil.isNull(opdynid)) {
            log.warn("打开页面异常:" + opsource + " opdynid:" + opdynid + " expand:" + expand);
            errorRedirect(response, "页面异常", "错误代码：DynNull 描述:页面ID错误");

        } else {

            // 调用腾讯获取OPENID
            String APPID = KHDBConfig.getParamConfig(eliteBean, opsource + "-appID");
            String APPSECRET = KHDBConfig.getParamConfig(eliteBean, opsource + "-appSecret");
            log.debug("获取到的腾讯公众号配置信息【APPID】：" + APPID + "【APPSECRET】：" + APPSECRET);

            // 如果未获取到对应APPID直接返回失败
            if (KHUtil.isNull(APPID) || KHUtil.isNull(APPSECRET)) {
                String err_Info = KHUtil.isNull(opsource) ? "当前入参opsource为空,请检查" : "当前来源:" + opsource + "未查询到对应APPID配置,请检查";
                errorRedirect(response, "页面异常", err_Info);
            }

            // 通过Code信息获取openid
            JSONObject apiTokenJson = new JSONObject();
            if (opsource == "wxc") {
                apiTokenJson = JSONObject.parseObject(Util.doHttpGet("https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + APPID + "&secret=" + APPSECRET + "&code=" + code + "&grant_type=authorization_code", "UTF-8", 5000, 0));
                log.debug("通过Code信息获取微信openid调用返回：" + apiTokenJson.toString());

            } else if (opsource == "wxq") {
                apiTokenJson = JSONObject.parseObject(Util.doHttpGet(KHDBConfig.getAPIURL(eliteBean, "SYS-InnerDomain") + "groovy/GeneralService/apiGetToken?appid=WXG_DAVCO", "UTF-8", 12000, 0));
                log.debug("通过配置信息获取企微access_token调用返回：" + apiTokenJson.toString());

                String callURL = "https://qyapi.weixin.qq.com/cgi-bin/auth/getuserinfo?access_token=" + apiTokenJson.getJSONObject("value").getString("access_token") + "&code=" + code;
                log.debug("获取企微-Code信息openid调用URL：" + callURL);

                apiTokenJson = JSONObject.parseObject(Util.doHttpGet(callURL, "UTF-8", 5000, 0));
                log.debug("通过Code信息获取企微openid调用返回：" + apiTokenJson.toString());

            }

            if (apiTokenJson.containsKey("openid") || apiTokenJson.containsKey("userid")) {
                String access_token = apiTokenJson.getString("access_token");
                String refresh_token = apiTokenJson.getString("refresh_token");
                String openid = apiTokenJson.getString("openid");
                String quserid = apiTokenJson.getString("userid");
                String scope = apiTokenJson.getString("scope");
                log.debug("获取到的腾讯用户信息【access_token】：" + access_token + "【refresh_token】：" + refresh_token + "【openid】：" + openid + "【userid】：" + quserid);

                // 检查当前OPENID对应的账号类型
                List selectExits = null;
                if (opsource == "wxc") {
                    selectExits = jt.queryForList("select customer_guid as userid, loginname, 'customer' as usertype, 2 as sno from customer where open_id = ? order by sno limit 1", openid);

                } else if (opsource == "wxq") {
                    selectExits = jt.queryForList("select staff_id as userid, loginname , 'staff' as usertype, 1 as sno from staff where userid = ? order by sno limit 1", quserid);

                } else {
                    log.warn("未知类型公众号嵌入获取用户信息警告:" + opsource);
                    errorRedirect(response, "页面异常", "未知类型公众号嵌入获取用户信息警告:" + opsource);
                }

                // 获取当前登录人在系统中的信息
                String userid = "";
                String usertype = "";
                if (selectExits.size() > 0) {
                    Map selectExitsm = selectExits.get(0);
                    userid = selectExitsm.get("userid");
                    usertype = selectExitsm.get("usertype");

                } else {
                    userid = openid;
                    usertype = "notype";
                }
                log.debug("获取当前登录人在系统中的信息:" + userid + "/" + usertype);

                // 获取NGS页面信息短码
                String NGSShortenLinkURL = out_DomainURL + "groovy/GeneralService/apiShortenLink?dynid=" + opdynid + "&userid=" + userid + "&usertype=" + usertype + "&woid=&taskid=" + taskid + "&expand=" + expand + "&cbtype=&opsource=" + opsource;
                log.debug("获取NGS短码调用URL：" + NGSShortenLinkURL);

                JSONObject apiLinkJson = JSONObject.parseObject(Util.doHttpGet(NGSShortenLinkURL, "UTF-8", 5000, 0));
                log.debug("获取NGS短码调用返回：" + apiLinkJson.toString());

                // 解析NGS短码调用返回
                String linkURL = apiLinkJson.getString("message");
                log.debug("获取NGS页面信息短码：" + linkURL);

                response.sendRedirect(linkURL);
            } else {
                String errcode = apiTokenJson.getString("errcode");
                String errmsg = apiTokenJson.getString("errmsg");
                log.warn("打开页面异常:" + opsource + " errcode:" + errcode + " errmsg:" + errmsg);
                errorRedirect(response, "页面异常", "错误代码：" + errcode + " 描述:" + errmsg);
            }
        }
    }

    // 异常&错误重定向
    public static void errorRedirect(HttpServletResponse response, String ErrorTitle, String ErrorInfo) {
        log.warn("异常&错误[apiDynLogin]重定向 ErrorTitle:" + ErrorTitle + " ErrorInfo:" + ErrorInfo);
        ErrorTitle = KHUtil.isNull(ErrorTitle) ? "页面异常" : ErrorTitle;
        ErrorInfo = KHUtil.isNull(ErrorInfo) ? "请稍后再试或联系管理员." : ErrorInfo;
        response.sendRedirect(out_DomainURL + "ngs/404.html?ErrorTitle=" + URLEncoder.encode(ErrorTitle, "UTF-8") + "&ErrorInfo=" + URLEncoder.encode("登录异常&错误:" + ErrorInfo, "UTF-8").replaceAll("\\+", "%20"));
    }

    // 工具方法
    public static String getQueryString(Map<String, String> params) {
        String url = "";
        if (params == null) {
            return url;
        }

        StringBuilder builder = new StringBuilder(url);

        int i = 0;
        for (String key : params.keySet()) {
            String value = params.get(key);
            if (value == null) { // 过滤空的key
                continue;
            }

            if (i != 0) {
                builder.append('&');
            }

            builder.append(key);
            builder.append('=');
            builder.append(encode(value));

            i++;
        }

        return builder.toString();
    }

    // 工具方法
    public static String encode(String input) {
        if (input == null) {
            return "";
        }

        try {
            return URLEncoder.encode(input, "utf-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        return input;
    }
}